package com.risk.ctrl.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.risk.ctrl.enums.ErrorCodeEnum;
import com.risk.ctrl.exceptions.BusinessException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class JacksonUtils {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    public static final String JSONARRAY = "JSONArray";
    public static final String JSONOBJECT = "JSONObject";
    public static final String UNKNOWN = "Unknown";
    private static final TypeFactory TYPE_FACTORY = OBJECT_MAPPER.getTypeFactory();

    static {
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }

    public static <T> String toJson(T obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.JACKSON_SERIALISE_EXCEPTION, e);
        }
    }

    public static <T> T fromJson(String json, Class<T> clazz) {
        try {
            return OBJECT_MAPPER.readValue(json, clazz);
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.JACKSON_DESERIALIZE_EXCEPTION, e);
        }
    }

    public static <T> T fromJson(String json, TypeReference<T> typeReference) {
        try {
            return OBJECT_MAPPER.readValue(json, typeReference);
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.JACKSON_DESERIALIZE_EXCEPTION, e);
        }
    }
    public static <T> T fromJson(String json, JavaType javaType) {
        try {
            return OBJECT_MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.JACKSON_DESERIALIZE_EXCEPTION, e);
        }
    }

    /**
     * 构建 List<T> 类型
     */
    public static JavaType listType(Class<?> elementClass) {
        return TYPE_FACTORY.constructCollectionType(List.class, elementClass);
    }

    /**
     * 构建 List<T> 类型
     */
    public static JavaType listType(JavaType elementClass) {
        return TYPE_FACTORY.constructCollectionType(List.class, elementClass);
    }

    /**
     * 构建 List<T> 类型
     */
    public static JavaType type(Class<?> elementClass) {
        return TYPE_FACTORY.constructType(elementClass);
    }    /**
     * 构建 Set<T> 类型
     */
    public static JavaType setType(Class<?> elementClass) {
        return TYPE_FACTORY.constructCollectionType(Set.class, elementClass);
    }

    /**
     * 构建 Map<K, V> 类型
     */
    public static JavaType mapType(Class<?> keyClass, Class<?> valueClass) {
        return TYPE_FACTORY.constructMapType(Map.class, keyClass, valueClass);
    }

    /**
     * 构建 Map<K, V> 类型
     */
    public static JavaType mapType(JavaType keyClass, JavaType valueClass) {
        return TYPE_FACTORY.constructMapType(Map.class, keyClass, valueClass);
    }
    /**
     * 构建数组类型
     */
    public static JavaType arrayType(Class<?> componentType) {
        return TYPE_FACTORY.constructArrayType(componentType);
    }

    /**
     * 构建任意参数化类型，如 Pair<String, List<Integer>>
     * 示例：parametricType(Pair.class, String.class, listType(Integer.class));
     */
    public static JavaType parametricType(Class<?> rawClass, JavaType... args) {
        return TYPE_FACTORY.constructParametricType(rawClass, args);
    }

    /**
     * 构建任意参数化类型（支持 Class 参数）
     */
    public static JavaType parametricType(Class<?> rawClass, Class<?>... args) {
        JavaType[] javaTypes = Arrays.stream(args)
                .map(TYPE_FACTORY::constructType)
                .toArray(JavaType[]::new);
        return TYPE_FACTORY.constructParametricType(rawClass, javaTypes);
    }

    /**
     * 构建嵌套泛型：Map<String, List<User>>
     */
    public static JavaType mapOfStringToListOf(Class<?> elementClass) {
        JavaType listType = listType(elementClass);
        return mapType(TYPE_FACTORY.constructType(String.class), listType);
    }

    /**
     * 构建：List<Map<String, T>>
     */
    public static JavaType listOfMapOfStringTo(Class<?> valueClass) {
        JavaType mapType = mapType(String.class, valueClass);
        return listType(mapType);
    }
    /**
     * 从 TypeReference 获取 JavaType（用于复杂场景）
     */
    public static JavaType getTypeReference(TypeReference<?> typeRef) {
        return TYPE_FACTORY.constructType(typeRef.getType());
    }
    /**
     * 判断字符串是否是json格式
     * @param json
     * @return
     */
    public static boolean isJson(String json) {
        try {
            OBJECT_MAPPER.readTree(json);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * json转对象
     * @param content
     * @return
     */
    public static String detectJsonType(String content) {
        try {
            JsonNode jsonNode = OBJECT_MAPPER.readTree(content);
            if (jsonNode.isArray()) {
                return JSONARRAY;
            } else if (jsonNode.isObject()) {
                return JSONOBJECT;
            }
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.JACKSON_DESERIALIZE_EXCEPTION, e);
            // Handle exception
        }
        return UNKNOWN;
    }
}
